using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.Threading;

namespace HW2and3
{
    class KTModelDFSLookAhead : ModelBase
    {        
        private int[] vertical = {-1, -2, -2, -1, 1, 2, 2, 1};
        private int[] horizontal = {2, 1, -1, -2, -2, -1, 1, 2};
        private bool[,] visited;
        public static int[,] accesibility;

        public KTModelDFSLookAhead() { }

        public override void Initialize(int sleepInterval, int size, int x, int y)
        {
            base.Initialize(sleepInterval, size, x, y);

            modelThread = new Thread(this.DFSStart);

            visited = new bool[size, size];
            accesibility = new int[size, size];
            PreCalculateAccesibility();
            for (int i = 0; i < size; i++)
                for (int j = 0; j < size; j++)
                    visited[i, j] = false;
        }

        public void PreCalculateAccesibility()
        {
            for(int i=0; i<accesibility.GetLength(0); i++)
            {
                for (int j = 0; j < accesibility.GetLength(1); j++)
                {
                    for (int k = 0; k < horizontal.Length; k++)
                    {
                        int a = vertical[k] + i;
                        int b = horizontal[k] + j;
                        if (a >= 0 && a < size && b >= 0 && b < size)
                            accesibility[i, j]++;
                    }
                }
            }
        }

        private void DFSStart()
        {
            KTStateKnight state = new KTStateKnight(size,x,y,true);
            Console.WriteLine("Iniciando el DFS");

            DFS(state, 1);
        }


        public bool DFS(KTStateKnight prevState, int index)
        {
            if (this.isStopped) return false;
            Sleep();

            ArrayList states = new ArrayList();
            index++;
            NotifyAll(prevState, (" X : " + (prevState.X) + " Y: " +  (prevState.Y)), "");
            if (visited[prevState.X, prevState.Y])
            {
                Console.WriteLine("{0},{1} - ha sido visitado", prevState.X, prevState.Y);
                return false;
            }
            else
            {
                Console.WriteLine("{0},{1} - No Ha sido visitado", prevState.X, prevState.Y);
                visited[prevState.X, prevState.Y] = true;
            }

            //Goal
            if (index == size * size + 1)
            {
                NotifyAll(prevState, "Fin", "Terminamos");
                return true;
            }

            for (int i = 0; i < horizontal.Length; i++)
            {
                int a = prevState.X + vertical[i];
                int b = prevState.Y + horizontal[i];
                if (a >= 0 && a < size && b >= 0 && b < size && prevState.Board[a,b] == 0)
                {
                    states.Add(prevState.GetNewState(a, b, index));
                }
            }
            states.Sort();

            foreach (KTStateKnight state in states)
            {
                Console.WriteLine("X : " + state.X + " Y: " + state.Y  + " Accesibility: " + accesibility[state.X, state.Y] + 
                    " Next Best; " + state.NextBestAccesibility);
            }
            foreach (KTStateKnight state in states)
            {
                if (DFS(state, index))
                    return true;
            }

            visited[prevState.X, prevState.Y] = false;
            NotifyAll(prevState, "Regresamos", "");
            return false;
        }
    }
}
